﻿#coding=utf-8
from models import *
from django.shortcuts import render_to_response
from django.http import Http404, HttpResponse, HttpRequest, HttpResponseRedirect,HttpResponseNotFound
from django.template import RequestContext
#from django.contrib import auth
#from django.contrib.auth.models import User
from forms import *
from utils import Paginator, InvalidPage, EmptyPage
from math import ceil
from django.core.urlresolvers import reverse

from google.appengine.api.users import *
from google.appengine.api import users

from models import UserProfile

def show_forums_index(request):
    user = users.get_current_user()
    if user and not UserProfile.all().filter('user = ', user).get():
        return HttpResponseRedirect('/forum/firstlogin/')
#        profile = UserProfile()
#        profile.user = users.get_current_user()
#        profile.nickname = profile.user.nickname()
#        profile.rank = 0
#        form = SettingsForm({
#                            'homepage':profile.homepage,
#                            'description':profile.description,
#                            }
#            )
#        return render_to_response("forum/user_settings.html", 
#                                  {'userprofile':profile,
#                                   'user': request.user,
#                                   'firsttime':True,
#                                   'form':form
#                                  },
##                                  context_instance=RequestContext(request)
#                                )
    '''
    Show forums index page
    '''
#    forum = Forum()
#    forum.name = u'论坛系统讨论区'
#    forum.save()
#    
    forums = Forum.all()   
    if forums.count() == 0:
        forum = Forum()
        forum.name = u'系统讨论区'
        forum.save()
        
    forums = Forum.all()
    
    total_topics = 0
    total_posts = 0
    for forum in forums:
        total_topics += forum.topics
        total_posts += forum.posts
        
    total_users = UserProfile.all().count()
    
    all_users = UserProfile.all().order('-date_joined')
    newest_user = all_users.get()
    # Response a index page.
    return render_to_response("forum/forums_index.html", {'forums':forums,'total_topics':total_topics,'total_posts':total_posts,'total_users':total_users,'newest_user':newest_user},context_instance=RequestContext(request))

def registers(request):
    '''
    Register a user
    '''
        
    if request.method == 'POST':
        form = RegisterForm(request.POST)
        if form.is_valid():
            user = User.objects.create_user(form.clean_data['username'], form.clean_data['email'], form.clean_data['password'])
            try:
                profile = user.get_profile()
            except UserProfile.DoesNotExist:
                profile = UserProfile()
                profile.user = user
                profile.save()
            #return HttpResponseRedirect('/contact/thanks/')
            return HttpResponseRedirect('/forum/login/')
    else:
        form = RegisterForm()
        
    return render_to_response('forum/register_user.html', {'form': form},context_instance=RequestContext(request))

def register(request, success_url=None,
             form_class=RegistrationForm, profile_callback=None,
             template_name='registration/registration_form.html',
             extra_context=None):
    """
    Allow a new user to register an account.
    
    Following successful registration, issue a redirect; by default,
    this will be whatever URL corresponds to the named URL pattern
    ``registration_complete``, which will be
    ``/accounts/register/complete/`` if using the included URLConf. To
    change this, point that named pattern at another URL, or pass your
    preferred URL as the keyword argument ``success_url``.
    
    By default, ``registration.forms.RegistrationForm`` will be used
    as the registration form; to change this, pass a different form
    class as the ``form_class`` keyword argument. The form class you
    specify must have a method ``save`` which will create and return
    the new ``User``, and that method must accept the keyword argument
    ``profile_callback`` (see below).
    
    To enable creation of a site-specific user profile object for the
    new user, pass a function which will create the profile object as
    the keyword argument ``profile_callback``. See
    ``RegistrationManager.create_inactive_user`` in the file
    ``models.py`` for details on how to write this function.
    
    By default, use the template
    ``registration/registration_form.html``; to change this, pass the
    name of a template as the keyword argument ``template_name``.
    
    **Required arguments**
    
    None.
    
    **Optional arguments**
    
    ``form_class``
        The form class to use for registration.
    
    ``extra_context``
        A dictionary of variables to add to the template context. Any
        callable object in this dictionary will be called to produce
        the end result which appears in the context.
    
    ``profile_callback``
        A function which will be used to create a site-specific
        profile instance for the new ``User``.
    
    ``success_url``
        The URL to redirect to on successful registration.
    
    ``template_name``
        A custom template to use.
    
    **Context:**
    
    ``form``
        The registration form.
    
    Any extra variables supplied in the ``extra_context`` argument
    (see above).
    
    **Template:**
    
    registration/registration_form.html or ``template_name`` keyword
    argument.
    
    """
    if request.method == 'POST':
        form = form_class(data=request.POST, files=request.FILES)
        if form.is_valid():
            new_user = form.save(profile_callback=profile_callback)
            # success_url needs to be dynamically generated here; setting a
            # a default value using reverse() will cause circular-import
            # problems with the default URLConf for this application, which
            # imports this file.
            return HttpResponseRedirect(success_url or reverse('registration_complete'))
    else:
        form = form_class()
    
    if extra_context is None:
        extra_context = {}
    context = RequestContext(request)
    for key, value in extra_context.items():
        context[key] = callable(value) and value() or value
    return render_to_response(template_name,
                              { 'form': form },
                              context_instance=context)

def activate(request, activation_key,
             template_name='registration/activate.html',
             extra_context=None):
    """
    Activate a ``User``'s account from an activation key, if their key
    is valid and hasn't expired.
    
    By default, use the template ``registration/activate.html``; to
    change this, pass the name of a template as the keyword argument
    ``template_name``.
    
    **Required arguments**
    
    ``activation_key``
       The activation key to validate and use for activating the
       ``User``.
    
    **Optional arguments**
       
    ``extra_context``
        A dictionary of variables to add to the template context. Any
        callable object in this dictionary will be called to produce
        the end result which appears in the context.
    
    ``template_name``
        A custom template to use.
    
    **Context:**
    
    ``account``
        The ``User`` object corresponding to the account, if the
        activation was successful. ``False`` if the activation was not
        successful.
    
    ``expiration_days``
        The number of days for which activation keys stay valid after
        registration.
    
    Any extra variables supplied in the ``extra_context`` argument
    (see above).
    
    **Template:**
    
    registration/activate.html or ``template_name`` keyword argument.
    
    """
    activation_key = activation_key.lower() # Normalize before trying anything with it.
    account = RegistrationProfile.objects.activate_user(activation_key)
    #if account:
        #user = authenticate(username=account.username, password=password)
        #from django.contrib.auth import login
        #login(request, account)
        
    if extra_context is None:
        extra_context = {}
    context = RequestContext(request)
    for key, value in extra_context.items():
        context[key] = callable(value) and value() or value
    return render_to_response(template_name,
                              { 'account': account,
                                'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS },
                              context_instance=context)


def enter_forum(request,forum_id):
    '''
    Enter a forum,list all topics for the forum.
    '''
    forum = Forum.get_by_id(long(forum_id))
    if forum == None:
        return HttpResponseNotFound('404')
    topics = Topic.all().filter('forum = ', forum).order('-last_datetime')
    paginator = Paginator(topics, 10)
    # Make sure page request is an int. If not, deliver first page.
    try:
        page = int(request.GET.get('page', '1'))
    except ValueError:
        page = 1

    # If page request (9999) is out of range, deliver last page of results.
    try:
        topics = paginator.page(page)
    except (EmptyPage, InvalidPage):
        topics = paginator.page(paginator.num_pages)
    all_forums = Forum.objects.all()
    # Response a index page.
    return render_to_response("forum/forum_page.html", {'forum':forum,'topics':topics,'all_forums':all_forums},context_instance=RequestContext(request))

def enter_topic(request,topic_id):
    '''
    Enter a topic,list all posts for the topic.
    '''
    topic = Topic.get_by_id(long(topic_id))
    if not topic :
        return HttpResponseNotFound('404')
        
    topic.views += 1
    topic.save()
    posts = Post.all().filter('topic =',topic).order('datetime1')
    paginator = Paginator(posts, 10)
    # Make sure page request is an int. If not, deliver first page.
    try:
        page = int(request.GET.get('page', '1'))
    except ValueError:
        page = 1

    # If page request (9999) is out of range, deliver last page of results.
    try:
        posts = paginator.page(page)
    except (EmptyPage, InvalidPage):
        posts = paginator.page(paginator.num_pages)
        
    all_forums = Forum.all()
    posts = Post.all().filter('topic =',topic).order('datetime1')
    # Response a index page.
    userprofile = UserProfile.all().filter('user = ', users.get_current_user()).get()
    return render_to_response("forum/topic_page.html", {'topic':topic,'posts':posts,'all_forums':all_forums, 'userprofile':userprofile},context_instance=RequestContext(request))

def enter_post(request,post_id):
    '''
    Enter a post,list the latest posts for the topic.
    '''

    post = Post.get_by_id(long(post_id))
    if post == None:
        return HttpResponseNotFound('404')
        
    post.topic.views += 1
    post.topic.save()
    posts = Post.all().filter('topic =', post.topic).order('datetime1')
    paginator = Paginator(posts, 10)
    
    post_num = post.num
    hits = max(1, post_num)
    num_page = int(ceil(hits / float(10)))

    # If page request (9999) is out of range, deliver last page of results.
    try:
        posts = paginator.page(num_page)
    except (EmptyPage, InvalidPage):
        posts = paginator.page(paginator.num_pages)
        
    all_forums = Forum.objects.all()
    # Response a index page.
    return render_to_response("forum/topic_page.html", {'topic':post.topic,'posts':posts,'all_forums':all_forums},context_instance=RequestContext(request))

def new_topic(request,forum_id):
    '''
    Create a new topic
    '''
    if _is_valid_user(request) == False:
        return login(request)
    
    if request.method == 'POST':
        form = NewTopicForm(request.POST)
        if form.is_valid():
            topic = Topic(subject=form.cleaned_data['subject'])
            topic.forum = Forum.get_by_id(long(forum_id))
            user = users.get_current_user()
            profile = UserProfile.all().filter('user =',user).get()
            if not profile:
                profile = UserProfile()
                profile.user = user
                profile.save()
            topic.author = profile
            topic.last_authorid = topic.author.key().id()
            topic.save()
            post = Post(content=form.cleaned_data['content'])
            post.topic = topic
            post.author = topic.author
            post.is_topic = True
            post.save()
            return HttpResponseRedirect('/forum/%s/topics/' % forum_id)
    else:
        form = NewTopicForm()
        
    return render_to_response('forum/new_topic.html', {'form': form},context_instance=RequestContext(request))

def new_post(request,topic_id):
    '''
    Create a new post
    '''
    if _is_valid_user(request) == False:
        return HttpResponseRedirect('/forum/login/')
    
    if request.method == 'POST':
        form = NewPostForm(request.POST)
        if form.is_valid():
            post = Post(content=form.cleaned_data['content'])
            post.topic = Topic.get_by_id(long(topic_id))
            profile = UserProfile.all().filter('user =',users.get_current_user()).get()
            post.author = profile
            post.topic.last_authorid = post.author.key().id()
            post.is_topic = False
            post.save()
            post_count = post.topic.replies + 1
            hits = max(1, post_count)
            num_pages = int(ceil(hits / float(10)))
            return HttpResponseRedirect('/forum/topic/%s/?page=%d#p%d' % (topic_id,num_pages,post.get_id()))
    else:
        form = NewPostForm()
        
    return render_to_response('forum/new_post.html', {'form': form},context_instance=RequestContext(request))

def edit_post(request,post_id):
    '''
    Edit a topic or post
    '''
    if _is_valid_user(request) == False:
        return HttpResponseRedirect('/forum/login/')
    
    post = Post.get_by_id(long(post_id))
    if not post:
        return HttpResponseNotFound('404')
    
    if users.get_current_user() != post.author.user:
        return HttpResponseNotFound('404')
    
    if request.method == 'POST':
        if post.is_topic == True:
            form = NewTopicForm(request.POST)
            if form.is_valid():
                post.topic.subject = form.cleaned_data['subject']
                post.topic.save()
                post.content = form.cleaned_data['content']
                post.save()
                return HttpResponseRedirect('/forum/topic/%s/' % post.topic.get_id())
            return render_to_response('forum/new_topic.html', {'form': form},context_instance=RequestContext(request))
        else:
            form = NewPostForm(request.POST)
            if form.is_valid():
                post.content = form.cleaned_data['content']
                post.save()
                post_num = post.num
                hits = max(1, post_num)
                num_page = int(ceil(hits / float(10)))
                return HttpResponseRedirect('/forum/topic/%s/?page=%d#p%d' % (post.topic.id,num_page,post.id))
            return render_to_response('forum/new_post.html', {'form': form},context_instance=RequestContext(request))
    else:
        if post.is_topic == True:
            form = NewTopicForm({'subject':post.topic.subject,'content':post.content})
            return render_to_response('forum/new_topic.html', {'form': form},context_instance=RequestContext(request))
        else:
            form = NewPostForm({'content':post.content})
            return render_to_response('forum/new_post.html', {'form': form},context_instance=RequestContext(request))
        
def user_settings(request):
    '''
    Set a user
    '''
    if _is_valid_user(request) == False:
        return login(request)

    profile = UserProfile.all().filter('user = ', users.get_current_user()).get()
    if not profile:
        profile = UserProfile()
        profile.user = users.get_current_user()
        profile.nickname = profile.user.nickname()
        firsttime = True
    else:
        firsttime = False
    
    savesuccess = False
        
    if request.method == 'POST':
        form = SettingsForm(request.POST)
        if form.is_valid():
            profile.city = request.POST.get('city','')
            profile.sex = request.POST.get('sex','')
            profile.description = form.cleaned_data['description']
            profile.homepage = form.cleaned_data['homepage']
    #            request.user.email = form.clean_data['email']
            profile.save()
            savesuccess = True
            return HttpResponseRedirect('/forum/')
        else:
            print 'not valid'
            print form.errors
    else:
        form = SettingsForm({
                            'homepage':profile.homepage,
                            'description':profile.description,
                            }
            )
        #form = SettingsForm()
        
    return render_to_response('forum/user_settings.html', 
                              {'form':form,
                               'userprofile':profile,
                               'savesuccess':savesuccess,
                               'firsttime':firsttime,
                               'user':request.user
                               },
#                               context_instance=RequestContext(request)
                               )

def user_profile(request,user_id):
    '''
    Show a user's profile
    '''
    try:
        dj_user = UserProfile.get_by_id(long(user_id))
    except UserProfile.DoesNotExist:
        return HttpResponseNotFound('404')
    if dj_user == None:
        return HttpResponseNotFound('404')
        
    return render_to_response('forum/user_profile.html', {'dj_user':dj_user})

def _is_valid_user(request):
    "check whether the user is valid and the user is authenticated"
    user = get_current_user()
    if not user:
        return False
    return True
#    if request.user.is_authenticated() and request.user.is_active:
#        return True
#    else:
#        return False

def login(request,*arg, **kw):
    response = HttpResponseRedirect(users.create_login_url("/forum/"))    
    return response
    
def firstlogin(request, *arg, **kw):
    profile = UserProfile()
    profile.user = users.get_current_user()
    profile.nickname = profile.user.nickname()
    profile.rank = 0

    if request.method == 'POST':
        form = SettingsForm(request.POST)
        if form.is_valid():
            profile.city = request.POST.get('city','')
#            profile.sex = request.POST.get('sex','')
            profile.description = form.cleaned_data['description']
            profile.homepage = form.cleaned_data['homepage']
    #            request.user.email = form.clean_data['email']
            profile.save()
            return HttpResponseRedirect('/forum/')
        else:
            print 'not valid'
            print form.errors
    else:
        form = SettingsForm({
                            'homepage':profile.homepage,
                            'description':profile.description,
                            }
            )
    
        form = SettingsForm({
                            'homepage':profile.homepage,
                            'description':profile.description,
                            }
            )
        return render_to_response("forum/user_settings.html", 
                                  {'userprofile':profile,
                                   'user': request.user,
                                   'firsttime':True,
                                   'form':form
                                  },
#                                  context_instance=RequestContext(request)
                                )

def logout(request,*arg, **kw):
    response = HttpResponseRedirect(users.create_logout_url("/"))    
    return response
    
    pass
